package cate.game.activity.limitshop;

import cate.common.table.activity.base.ShopActivityBaseRow;
import cate.common.table.activity.limitshopactivity.row.LimitShopActivityBaseRow;
import cate.common.table.d.GDOperation;
import cate.common.table.pay.PayItemRow;
import cate.common.util.GameResult;
import cate.game.activity.base.core.RoleActivitySingle;
import cate.game.activity.limitshop.msg.LimitShopActivityInfoResp;
import cate.game.res.MixRes;
import cate.game.res.MixResAdder;
import cate.game.res.MixResItem;
import cate.game.role.Role;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;
import easy.java.practice.errorcode.EcResult;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@NoteClass("限购商店")
public class LimitShopActivity extends RoleActivitySingle {
    @NoteField(value = "限购数量记录")
    public Map<Integer, Integer> buyRecords;

    @Override
    public void initialize(Role role) {
        super.initialize(role);
        if (buyRecords == null) {
            buyRecords = new HashMap<>();
        }
    }

    @Override
    public void excelCheck() {
        Map<Integer, ShopActivityBaseRow> allConfigs = getConfigs();
        if (allConfigs.isEmpty()) {
            buyRecords.clear();
            return;
        }
        buyRecords.entrySet().removeIf(kv -> !allConfigs.containsKey(kv.getKey()));
        for (ShopActivityBaseRow config : allConfigs.values()) {
            if (!buyRecords.containsKey(config.id)) {
                buyRecords.put(config.id, 0);
            }
        }
    }


    public void noticeUpdate() {
        role.sendNow(new LimitShopActivityInfoResp(this));
    }

    private Predicate<? super Integer> createResetConsume(int resetType){
        return (k) -> {
            ShopActivityBaseRow config = getConfig(k);
            return config != null && config.resetType == resetType;
        };
    }

    protected boolean resetRecords(int resetType){
        AtomicBoolean anyMatch = new AtomicBoolean(false);
        Predicate<? super Integer> action = createResetConsume(resetType);
        buyRecords.entrySet().forEach(e -> {
            if(action.test(e.getKey())){
                e.setValue(0);
                anyMatch.set(true);
            }
        });
        return anyMatch.get();
    }

    @Override
    public void onDaySpan(boolean silence) {
        super.onDaySpan(silence);
        excelCheck();
        resetRecords(1);
        if (!silence) {
            noticeUpdate();
        }
    }

    @Override
    public void onRoleOpen() {

    }

    @Override
    public void onRoleEnd() {
        buyRecords.clear();
    }

    @Override
    public void initSend() {
        noticeUpdate();
    }

    @Override
    public void onWeekSpan(boolean silence){
        resetRecords(2);
        if (!silence) {
            noticeUpdate();
        }
    }

    @Override
    public void onMonthSpan(boolean silence){
        resetRecords(3);
        if (!silence) {
            noticeUpdate();
        }
    }

    @Override
    public GameResult<Void> allowPay(PayItemRow pir) {
        GameResult<Void> r = new GameResult<>();
        int tid = pir.funcSubId;
        if (!buyRecords.containsKey(tid)) {
            return r.fail("未找到配置1");
        }
        ShopActivityBaseRow config = getConfig(tid);
        if (config == null) {
            return r.fail("未找到配置2");
        }
        if (config.openDay > role.getGame().getOpenDay()) {
            return r.fail("开服天数不足");
        }
        if (config.limit != -1) {
            if (buyRecords.get(tid) + 1 > config.limit) {
                return r.fail("限购次数不足");
            }
        }
        if (config.type != ShopActivityBaseRow.SHOP_TYPE_PAY) {
            return r.fail("不支持此购买模式");
        }
        MixRes rewardRes = new MixRes(config.rewardStr);
        if (rewardRes.isEmpty()) {
            return r.fail("奖励为空");
        }
        return r.success();
    }

    /**
     * 获取操作类型
     */
    @JsonIgnore
    protected int getGDOperation() {
        switch (funcId()) {
//            case GDFunc.ACT_HERO_UP_LIMIT_SHOP:
//            case GDFunc.ACT_HERO_UP_LIMIT_SHOP_EX:
//                return GDOperation.ACT_HERO_UP_LIMIT_SHOP;
            default:
                return GDOperation.LIMIT_SHOP_BUY;
        }
    }

    /**
     * 获取单条商品配置
     *
     * @param tid 配置ID
     */
    @JsonIgnore
    protected ShopActivityBaseRow getConfig(int tid) {
        switch (funcId()) {
//            case GDFunc.ACT_HERO_UP_LIMIT_SHOP:
//            case GDFunc.ACT_HERO_UP_LIMIT_SHOP_EX:
//                return role.getGame().table.heroUp.shop.get(tid);
            default:
                LimitShopActivityBaseRow baseRow = role.getGame().table.limitShopActivity.base.get(configTid());
                if(baseRow != null){
                    if ("限时商店活动.兑换商城".equals(baseRow.tplName)) {
                        return role.getGame().table.limitShopActivity.exchange.get(tid);
                    } else {
                        return role.getGame().table.limitShopActivity.item.get(tid);
                    }
                }
                return null;
        }
    }

    @Override
    public void onPaySuccess(PayItemRow payItemRow) {
        provideReward(payItemRow.funcSubId, 1, true);
        noticeUpdate();
    }

    /**
     * 获取活动内所有商品配置
     */
    @JsonIgnore
    protected Map<Integer, ShopActivityBaseRow> getConfigs() {
        Map<Integer, ShopActivityBaseRow> retMap = new HashMap<>();
        switch (funcId()) {
//            case GDFunc.ACT_HERO_UP_LIMIT_SHOP:
//            case GDFunc.ACT_HERO_UP_LIMIT_SHOP_EX: {
//                for (HeroUpShopRow config : role.getGame().table.heroUp.shop.getList()) {
//                    if (config.group == configTid()) {
//                        retMap.put(config.id, config);
//                    }
//                }
//            }
//                break;
            default:
                LimitShopActivityBaseRow baseRow = role.getGame().table.limitShopActivity.base.get(configTid());
                if(baseRow != null){
                    if ("限时商店活动.兑换商城".equals(baseRow.tplName)) {
                        retMap.putAll(role.getGame().table.limitShopActivity.exchange.getItems(baseRow.group, role.getGame().getOpenDay())
                                .stream().collect(Collectors.toMap(e -> e.id, v -> v)));
                    } else {
                        retMap.putAll(role.getGame().table.limitShopActivity.item.getItems(baseRow.group, role.getGame().getOpenDay())
                                .stream().collect(Collectors.toMap(e -> e.id, v -> v)));
                    }
                }
                break;
        }
        return retMap;
    }

    /**
     * 购买商品
     *
     * @param tid 配置ID
     * @param num 数量
     * @return 购买结果 携带自身活动数据
     */
    public GameResult<LimitShopActivity> buyItem(int tid, int num) {
        GameResult<LimitShopActivity> r = new GameResult<>();
        r.data = this;
        if (!buyRecords.containsKey(tid)) {
            return r.fail("未找到配置1");
        }
        ShopActivityBaseRow config = getConfig(tid);
        if (config == null) {
            return r.fail("未找到配置2");
        }
        if (config.openDay > role.getGame().getOpenDay()) {
            return r.fail("开服天数不足");
        }
        if (config.limit != -1) {
            if (buyRecords.get(tid) > config.limit - num) {
                return r.fail("限购次数不足");
            }
        }
        if (config.type == ShopActivityBaseRow.SHOP_TYPE_PAY) {
            return r.fail("不支持此购买模式");
        }
        MixRes rewardRes = new MixRes(config.rewardStr);
        if (rewardRes.isEmpty()) {
            return r.fail("奖励为空");
        }
        MixRes costRes = new MixRes(config.costStr);
        if (!costRes.isEmpty()) {
            costRes.items.forEach(item -> item.num *= num);
            EcResult<MixResItem> r_res = costRes.consumeCheck(role, null);
            if (!r_res.ok()) {
                return r.fail(r_res.message);
            }
            role.log.setOperation(getGDOperation(), tid);
            costRes.consume(role);
            role.log.clearOperation();
        }
        provideReward(tid, num, true);
        return r.success();
    }

    /**
     * 发放物品
     *
     * @param tid 配置ID
     * @param num 数量
     */
    protected MixRes provideReward(int tid, int num, boolean dialog) {
        if (!buyRecords.containsKey(tid)) {
            return null;
        }
        ShopActivityBaseRow config = getConfig(tid);
        if (config == null) {
            return null;
        }
        MixRes rewardRes = new MixRes(config.rewardStr);
        if (rewardRes.isEmpty()) {
            return null;
        }
        buyRecords.put(tid, buyRecords.get(tid) + num);
        rewardRes.items.forEach(item -> item.num *= num);
        new MixResAdder().setRes(rewardRes)
                .setOperation(getGDOperation())
                .setOperationSub(tid)
                .setDialogReward(dialog)
                .setSendMailWhenFull(true)
                .exe(role);
        return rewardRes;
    }
}
